package com.blog.vueblogx.config.shiro;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.blog.vueblogx.common.lang.Result;
import com.blog.vueblogx.util.JwtUtils;
import io.jsonwebtoken.Claims;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExpiredCredentialsException;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.ExpressionException;
import org.springframework.stereotype.Component;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * @version 1.0
 * @Author: 许啸林
 * @Date: 2022/2/14 14:12
 */
@Component
public class JwtFilter extends AuthenticatingFilter {
    @Autowired
    JwtUtils jwtUtils;

    @Override
    protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String jwt = request.getHeader("Authorization");
        if(StringUtils.isEmpty(jwt)) {
            return null;
        }
        return new JwtToken(jwt);
    }

    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String jwt = request.getHeader("Authorization");
        if(StringUtils.isEmpty(jwt)) {
            return true;
        }
        Claims claim = jwtUtils.getClaimByToken(jwt);
        if(claim == null || jwtUtils.isTokenExpired(claim.getExpiration())) {
            throw new ExpiredCredentialsException("登录令牌失效,请重新登录");
        }
        return executeLogin(servletRequest, servletResponse);
    }

    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {

        try {
            Throwable throwable = e.getCause() == null ? e : e.getCause();
            Result result = Result.error(throwable.getMessage());
            String jsonResult = JSONUtil.toJsonStr(result);
            HttpServletResponse rp = (HttpServletResponse) response;
            rp.getWriter().print(jsonResult);
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
        return false;
    }
}
